package com.rolfhoward.audio.manager

import android.media.AudioAttributes
import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioTrack
import android.os.Build
import java.io.File
import java.io.FileInputStream
import java.lang.Exception

/**
 *@author wuqiubin
 *@date 2022/9/10
 *@Describe
 */
class AudioPlayManager private constructor() {
    private var sampleRateInHz = 0
    private var channelConfig = 0
    private var audioFormat = 0
    private var bufferSize = 0

    private var audioTrack: AudioTrack? = null
    private var audioTrackThread: Thread? = null

    companion object {
        private var instance: AudioPlayManager? = null

        @Synchronized
        fun get(): AudioPlayManager {
            if (null == instance) {
                instance = AudioPlayManager()
            }
            return instance!!
        }
    }

    fun initAudioTrack() {
        sampleRateInHz = 44100
        channelConfig = AudioFormat.CHANNEL_OUT_MONO  //输出声道
        audioFormat = AudioFormat.ENCODING_PCM_16BIT
        bufferSize = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat)


    }

    fun audioTrackPlay(pcmPath: String) {
        releaseAudioTrack()
        var state = initAudioTrackWithMode(AudioTrack.MODE_STREAM, bufferSize)
        if (state == AudioTrack.STATE_UNINITIALIZED) {
            return
        }
        var pcmFile = File(pcmPath)
        if (!pcmFile.exists()) {
            return
        }
        audioTrackThread = Thread {
            var fileInputStream:FileInputStream? = null
            try {
                fileInputStream = FileInputStream(pcmFile)
                var buffer = ByteArray(bufferSize / 2)
                //stream模式，可以先调用play
                audioTrack?.play()
                var readCount = 0
                while (fileInputStream.available() > 0) {
                    readCount = fileInputStream.read(buffer)
                    if (readCount == AudioTrack.ERROR_BAD_VALUE || readCount == AudioTrack.ERROR_INVALID_OPERATION) {
                        continue;
                    }
                    if (audioTrack == null) {
                        return@Thread
                    }
                    //一次一次的写入pcm数据到audioTrack.由于是在子线程中进行write，快速连续点击可能主线程触发了stop或者release，导致子线程write异常：IllegalStateException: Unable to retrieve AudioTrack pointer for write()
                    //所以加playstate的判断
                    if (readCount > 0 && audioTrack != null && audioTrack?.playState == AudioTrack.PLAYSTATE_PLAYING && audioTrack?.state == AudioTrack.STATE_INITIALIZED) {
                        audioTrack?.write(buffer, 0, readCount);
                    }
                }
            }catch (e: Exception){}finally {
                try {
                    fileInputStream?.close()
                }catch (e: Exception){}
            }
        }
        audioTrackThread?.start()
    }

    fun audioTrackPause(){
        if (audioTrack?.state!! > AudioTrack.STATE_INITIALIZED){
            audioTrack?.pause()
        }
        audioTrackThread?.interrupt()
    }

    private fun initAudioTrackWithMode(mode: Int, bufferSize: Int): Int? {
        audioTrack = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            var attributes = AudioAttributes.Builder()
                //设置内容类型为语音时使用的内容类型
                .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                .setUsage(AudioAttributes.USAGE_ASSISTANT)
                .build()
            var audioFormat = AudioFormat.Builder()
                .setSampleRate(sampleRateInHz)
                .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                .build()
            AudioTrack(
                attributes,
                audioFormat,
                bufferSize,
                mode,
                AudioManager.AUDIO_SESSION_ID_GENERATE
            )
        } else {
            AudioTrack(
                AudioManager.STREAM_MUSIC,
                sampleRateInHz,
                channelConfig,
                audioFormat,
                bufferSize,
                mode,
                AudioManager.AUDIO_SESSION_ID_GENERATE
            )
        }
        return audioTrack?.state
    }

    /**
     * 释放播放器资源
     * */
    private fun releaseAudioTrack() {
        if (audioTrack?.state == AudioTrack.STATE_UNINITIALIZED) {
            audioTrack?.stop()
            audioTrack?.release()
        }
        audioTrackThread?.interrupt()
    }
}